#ifndef __TIMER_H__
#define __TIMER_H__

#include<memory>
#include"thread.h"
#include<set>
#include<vector>

namespace sylar{
class TimerManager;

class Timer : public std::enable_shared_from_this<Timer>{

friend class TimerManager;

public:
    using ptr = std::shared_ptr<Timer>;

    bool cancel();
    bool reset(uint64_t ms, bool from_now);
    bool refresh();
    
private:
    /**
     * @brief Construct a new Timer object
     * 
     * @param ms :定时事件
     * @param cb ：回调
     * @param recurring ：循环定时 
     * @param manager 
     */
    Timer(uint64_t ms, std::function<void()> cb, bool recurring, TimerManager* manager);

    Timer(uint64_t next): m_next(next){}
    
    //比较运算，用于定时器排序
    struct Compartor{
        bool operator()(const Timer::ptr& lhs, const Timer::ptr& rhs) const;
    };

private:
    bool m_recurring = false;    //是否循环定时
    uint64_t m_ms = 0;           //执行周期
    uint64_t m_next = 0;         //执行时间
    std::function<void()> m_cb;
    TimerManager* m_manager = nullptr;
};

class TimerManager{

friend class Timer;

public:
    using RWMutexType = RWMutex;

    TimerManager();

    virtual ~TimerManager();

    Timer::ptr addTimer(uint64_t ms, std::function<void()> cb, bool recurring = false);
    void addTimer(sylar::Timer::ptr val, sylar::RWMutex::WriteLock &lock);
    /**
     * @brief 条件定时器
     * 
     * @param ms 
     * @param cb 
     * @param weak_cond 智能指针作为控制的条件
     * @param recurring 
     * @return Timer::ptr 
     */
    Timer::ptr addConditionTimer(uint64_t ms, std::function<void()> cb, 
                std::weak_ptr<void> weak_cond, bool recurring=false);

    // 下一个定时器的执行时间
    uint64_t getNextTimer();

    // 已经超时的回调，可以放入到schedule里去执行
    void listExpiredCb(std::vector<std::function<void()>> &cbs);
    bool detectClockRollover(uint64_t now_ms);

    bool hasTimer();
protected:
    // 插入到最前端的timer需要去唤醒
    virtual void onTimerInsertedAtFront() = 0;
private:
    RWMutexType m_mutex;
    bool m_tickled = false;
    std::set<Timer::ptr, Timer::Compartor> m_timers;

    uint64_t m_previouseTime = 0;   // 上次执行时间
};

}


#endif